<?php

/*
 * This script belongs to Aspect PHP.
 *
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * This script is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-
 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details.
 */

/**
 * aspectContainerBuilder allows to create an aspect container from the
 * annotations of the aspect classes
 *
 * @package    aspectPhp
 * @subpackage lib
 * @author     gboisse
 */
class aspectContainerBuilder extends aspectContainer {

    /**
     * Creates a new instance for the aspectContainer and scans the
     * given aspect classes for AOP annotations
     *
     * @param  mixed The class names of the aspect classes
     */
    public function __construct() {
        parent::__construct();

        $aspectClasses = func_get_args();
        if (is_array($aspectClasses[0])) {
            $aspectClasses = $aspectClasses[0];
        }
        foreach ($aspectClasses as $aspectClass) {
            $this->scanForAspectPointcuts($aspectClass);
        }
    }

    /**
     * Scans the given aspect class for the pointcuts to register within the
     * aspect container
     *
     * @param string $className The aspect class to scan
     */
    public function scanForAspectPointcuts($className) {

        $class = new ReflectionClass($className);
        $classAnnotations = aspectUtils::parseAnnotations($class->getDocComment());

        if (isset($classAnnotations['aspect'])) {
            $methods = $class->getMethods();

            foreach ($methods as $method) {
                $methodAnnotations = aspectUtils::parseAnnotations($method->getDocComment());

                if (isset($methodAnnotations['around'])) {
                    $when = 'doAround';
                    $pointcutPattern = $methodAnnotations['around'][0];
                } elseif (isset($methodAnnotations['before'])) {
                    $when = 'doBefore';
                    $pointcutPattern = $methodAnnotations['before'][0];
                } elseif (isset($methodAnnotations['after'])) {
                    $when = 'doAfter';
                    $pointcutPattern = $methodAnnotations['after'][0];
                } elseif (isset($methodAnnotations['afterReturning'])) {
                    $when = 'doAfterReturning';
                    $pointcutPattern = $methodAnnotations['afterReturning'][0];
                } elseif (isset($methodAnnotations['afterThrowing'])) {
                    $when = 'doAfterThrowing';
                    $pointcutPattern = $methodAnnotations['afterThrowing'][0];
                } else {
                    continue;
                }

                $this->$when($pointcutPattern, $className, $method->getName());
            }
        }
    }

}
